#ifndef MANIFOLD_CUT_PROCESSOR_H
#define MANIFOLD_CUT_PROCESSOR_H

#include <vector>
#include "object.h"
#include "Moller97.h"
#include "point_operator.h"
using namespace std;

class manifold_cut_processor{
	struct edge{
		int pt0, pt1; 
		int tri_index;
		int version;
	};
private:
	vector<edge> unknown_shared_edge;
	point_operator op;
	Moller97 moller;
	
	void GetFirstTrianglePairThatIntersects();
	bool GetTriangleIntersectionsWithCutSegment(object *obj,int tri_index, float cut_pt0[3], float cut_pt1[3], float r0[3], float r1[3]);
	void GetNextTwoTrianglesThatIntersect(object *obj0, object *obj1, int &tri_index0, int &tri_index1, Point traversal_end_pt[3], Point intersectpt0[3], Point intersectpt1[3], int type0, int type1);
	void GetTraversalEndPoint(object *obj, Point intersectpt0[3],Point intersectpt1[3], Point traversal_end_pt[3]);
	void GetNeighbourTrianglesOfTriangleIndexThatHasTheSameVertexIndex(object *obj, int tri_index, int vertex_ref, vector<int> &neighbour_tri);
	int  GetAliveChildTriangleIndexThatHasVertexIndex(object *obj, int parent_index, int vertex_index);

	void TriangleDivisionOnTriangleThatIsAlive(object *obj,int tri_index,Point r0[3], Point r1[3], int type0, int type1);
	void TriangleDivisionAtChildLevel(object *obj0, object *obj1, int tri_index0, int tri_index1, Point parent_pt0[3][3], Point intersectpt0[3], Point intersectpt1[3], int &intersect_type0, int &intersect_type1);
	void TriangleDivisionOnAdjacentTriangle(object *obj, int tri_index, Point pt[3][3],Point r0[3], Point r1[3], int type0, int type1);
	void EdgePointDivision(object *obj, int parent_index, float p[3], int edge);
	void EdgePointDivisionOnAdjacentTriangle(object *obj, triangle current_tri,  float r[3], int type);
	void EndPointDivision(object *obj, int parent_index, float p[3]);

	int  CompareEdgeAndReturnTriangleIndex(object *obj, int p0, int p1, int tri_index, int version);
	int  DeterminePointType(Point[3][3], Point[3]);
	void AddUnknownSharedEdge(int, int, int,int);

	void ContinueUsingTheSameTriangleOrAdjacentTriangle(object *obj0, object *obj1, int &tri_index0, int &tri_index1, int type0, int type1);
	void MultipleTriangleWithTheSameOrAdjacentTriangle(object *fix_adj_obj, object *multi_obj, int &fix_adj_tri_index, int &multi_tri_index1, int fix_adj_type, int multi_type, Point end_pt[3]);
	void MultipleTriangleWithMultipleTriangle(object *obj0, object *obj1, int &tri_index0, int &tri_index1, Point end_pt[3]);
	
public:
	object *obj0_;
	object *obj1_;
	int start_tri_index0_;
	int start_tri_index1_;
	vector<int> exact_cut_path_;
	vector<int> rough_cut_path_;

	manifold_cut_processor(object *obj0, object *obj1);
	void ManifoldCut();
};

#endif